package check

import (
	"gitee.com/u-language/u-language/ucom/ast"
	"gitee.com/u-language/u-language/ucom/astdata"
	"gitee.com/u-language/u-language/ucom/errcode"
	"gitee.com/u-language/u-language/ucom/internal/utils"
)

// checkConst 检查变量
//   - ptr是被检查的常量节点，不能为nil
//   - sbt是被检查的常量节点所属代码块的符号表，不能为nil
//   - t是所属的抽象语法树
//   - InAutoFree是是否在自动释放块内
func checkConst(ptr *ast.ConstNode, sbt *ast.Sbt, t *ast.Tree, InAutoFree bool) (code errcode.ErrCode, msg errcode.Msg) {
	defer check_recover(&code, &msg)
	checkType(ptr.TYPE, sbt) //检查类型
	if ptr.Value != nil {    //如果变量声明同时进行初始化
		code, msg, src := ret_type_str(ptr.Value, sbt, t, InAutoFree)
		if code != errcode.NoErr {
			return code, msg
		}
		if src != ptr.TYPE.Typ() {
			return errcode.TypeIsNotEqual, errcode.NewMsgAssignTypeIsNotEqual(ptr.TYPE.Typ(), src)
		}
	}
	return
}

func checkType(typ astdata.Typ, sbt *ast.Sbt) ast.SymbolInfo {
	//查询变量声明的类型是否存在
	if o, ok := typ.(*ast.Object); ok {
		return sbt.HaveType(o.Name)
	} else if i, ok := typ.(*ast.ContinuityType); ok {
		return checkType(i.TYPE, sbt)
	} else if _, ok := typ.(*ast.GenericInstantiation); ok {
		return sbt.Have(typ.Typ())
	} else {
		o := typ.(*ast.Objects)
		return sbt.HaveType(utils.GeneratePackageSymbol(o.Slice[0].Name, o.Slice[1].Name))
	}
}
